package fetchserver

import (
	"neecola.com/learngo/zhenai/models"
	"regexp"
	"fmt"
	"strings"
	"strconv"
	"net/http"
	"log"
	"bufio"
	"io/ioutil"
	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/unicode"
	"errors"
	"golang.org/x/net/html/charset"
	"golang.org/x/text/transform"
)

var (
	zhenaiCityListReg = regexp.MustCompile(`<a href="(http://www.zhenai.com/zhenghun/[0-9a-zA-Z]+)"
									class="">([^<]+)</a>`)

	userUrlReg = regexp.MustCompile(`<link rel="canonical" href="(http://album.zhenai.com/u/[0-9]+)" />`)
	nameReg    = regexp.MustCompile(` <h1 class="ceiling-name ib fl fs24 lh32 blue">([^<]+)</h1> `)
	// 体重
	weightReg = regexp.MustCompile(`<td><span class="label">体重：</span><span field="">([^<]+)</span></td>`)
	// 性别
	genderReg = regexp.MustCompile(` <td><span class="label">性别：</span><span field="">([^<]+)</span></td>`)
	// 工作地
	jobLocationReg = regexp.MustCompile(` <td><span class="label">工作地：</span>([^<]+)</td>`)
	// 工作
	jobReg = regexp.MustCompile(`<td><span class="label">职业： </span>([^<]+)</td>`)
	//年龄
	ageReg = regexp.MustCompile(`<td><span class="label">年龄：</span>([^<]+)</td>`)
	// 身高
	heightReg = regexp.MustCompile(`<td><span class="label">身高：</span>([^<]+)</td>`)
	// 收入
	incomeReg = regexp.MustCompile(`<td><span class="label">月收入：</span>([^<]+)</td>`)
	// 婚姻状况
	marriageReg = regexp.MustCompile(`<td><span class="label">婚况：</span>([^<]+)</td>`)
	// 教育情况
	educationReg = regexp.MustCompile(`<td><span class="label">学历：</span>([^<]+)</td>`)
	// 星座
	constellationReg = regexp.MustCompile(`<td><span class="label">星座：</span>([^<]+)</td>`)
	// Birthplace 籍贯 出生地
	birthplaceReg = regexp.MustCompile(`<td><span class="label">籍贯：</span>([^<]+)</td>`)

	lifeReg       = regexp.MustCompile(`<td><span class="label">住房条件：</span><span field="">([^<]+)</span></td>`)
	thinkShelfReg = regexp.MustCompile(` <div class="info-text">
                            <p class="fs14 lh20 c5e slider-area-js">([^<]+)<span class="info-mark"></span></p>
                        </div>`)

	userReg = regexp.MustCompile(`<a href="(http://album.zhenai.com/u/[0-9]+)" target="_blank">`)

	// userReg = regexp.MustCompile(`<a href="(http://album.zhenai.com/u/[0-9]+)" target="_blank">`)
	nextPageReg = regexp.MustCompile(`<a class="next-page"
				href="(http://www.zhenai.com/zhenghun/[a-zA-Z/0-9]+)">`)
)

type Fetch struct {
}

// 获取指定 用户的用户信息
func (f *Fetch) FetchProfile(url string, profile *models.Profile) (err error) {

	data, err := fetchData(url)
	if err != nil {
		return err
	}
	// 解析人物的信息
	parserProfile(data, profile)

	profile.InsertOrUpdate()
	return nil
}

// 提取所有城市的连接
func (f *Fetch) FetchCityList(url string, list *[] models.CityInfo) (err error) {
	data, err := fetchData(url)
	if err != nil {
		return err
	}

	matches := zhenaiCityListReg.FindAllSubmatch(data, -1)

	for _, m := range matches {
		var c models.CityInfo
		for index := range m {
			if index == 0 {
				continue
			}

			if 1 == index {
				c.Url = string(m    [index])
			}

			if 2 == index {
				c.Name = string(m[index])

				*list = append(* list, c)
			}

			//
			log.Printf("index [%d] = %s \n", index, string(m[index]))
		}

	}
	return nil
}

// 提取城市的用户url 和城市的下一个的连接
func (f *Fetch) FetchCity(url string, info *models.CityMoreInfo) (err error) {
	data, err := fetchData(url)
	if err != nil {
		return err
	}

	userMatches := userReg.FindAllSubmatch(data, -1)

	for _, v := range userMatches {

		info.UserUrl = append(info.UserUrl, string(v[1]))
	}

	nextMatch := nextPageReg.FindSubmatch(data)

	if len(nextMatch) < 2 {
		return nil
	}

	// 下一页的信息
	info.NextPage = string(nextMatch[1])

	return nil
}

func fetchData(url string) (data []byte, err error) {

	request, err := http.NewRequest(http.MethodGet, url, nil)

	if err != nil {
		log.Printf("error **** %s \n", err.Error())
		return nil, err
	}

	request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")
	// 新生成的client代替默认的client
	client := http.Client{}

	resp, err := client.Do(request)

	if err != nil {
		log.Printf("error sub soodssss  %s \n", err.Error())
		return nil, err
	}

	defer resp.Body.Close()

	newReader := bufio.NewReader(resp.Body)

	uEncoding := determineEncoding(newReader)

	determineReader := transform.NewReader(newReader, uEncoding.NewDecoder())

	data, err = ioutil.ReadAll(determineReader)

	return data, err

}

// 返回获取网页的编码
func determineEncoding(reader *bufio.Reader) (uEncoding encoding.Encoding) {
	data, err := reader.Peek(1024)

	if err != nil {
		return unicode.UTF8
	}

	uEncoding, _, _ = charset.DetermineEncoding(data, "")
	return uEncoding
}

func parseProperty(data []byte, propertyReg *regexp.Regexp) (result string, err error) {

	matches := propertyReg.FindSubmatch(data)

	//for  index  , m := range  matches{
	//	log.Printf("m = [%d] = %s \n", index, string(m))
	//}

	if len(matches) < 2 {
		return "", errors.New("not found the property")
	}
	return string(matches[1]), nil
}

// 解释人物的信息
func parserProfile(data []byte, profile *models.Profile) {
	var result string
	var err error

	// 解析人物的姓名
	result, err = parseProperty(data, nameReg)

	if err == nil {
		profile.Name = result
	} else {
		log.Printf("error parse name %v \n", err)
	}

	// 解释性别
	result, err = parseProperty(data, genderReg)

	if err != nil {
		log.Printf("error parser gender %v\n", err)
	} else {
		profile.Gender = result
	}

	// 解释 工作
	result, err = parseProperty(data, jobReg)

	if err != nil {
		log.Printf("error parser job %v \n", err)
	} else {
		profile.Job = result
	}

	// 解释出生地
	result, err = parseProperty(data, birthplaceReg)

	if err != nil {
		fmt.Printf("error parser birthplace %v \n", err)
	} else {
		profile.BirthPlace = result
	}

	// 解析教育 ....
	result, err = parseProperty(data, educationReg)
	if err != nil {
		fmt.Printf("error parser education  %v \n", err)
	} else {
		profile.Education = result
	}

	result, err = parseProperty(data, heightReg)
	if err != nil {
		fmt.Printf("error parser height  %v \n", err)
	} else {
		profile.Height = result
	}

	result, err = parseProperty(data, weightReg)
	if err != nil {
		fmt.Printf("error parser weight  %v \n", err)
	} else {
		profile.Weight = result
	}

	result, err = parseProperty(data, incomeReg)
	if err != nil {
		fmt.Printf("error parser income  %v \n", err)
	} else {
		profile.Income = result
	}

	// 婚姻状况
	result, err = parseProperty(data, marriageReg)
	if err != nil {
		fmt.Printf("error parser marriage  %v \n", err)
	} else {
		profile.Marriage = result
	}

	// 年龄
	result, err = parseProperty(data, ageReg)
	if err != nil {
		fmt.Printf("error parser age  %v \n", err)
	} else {
		profile.Age = result
	}

	// 工作地
	result, err = parseProperty(data, jobLocationReg)
	if err != nil {
		fmt.Printf("error parser joblocation  %v \n", err)
	} else {
		profile.JobLocation = result
	}

	// url
	result, err = parseProperty(data, userUrlReg)
	if err != nil {
		fmt.Printf("error parser user %v \n", err)
	} else {
		profile.Url = result
	}

	if profile.Url != "" {
		split := strings.Split(profile.Url, "/")
		profile.UserElId = split[len(split)-1]
	}

	// 转化 Id
	profile.Id, _ = strconv.ParseInt(profile.UserElId, 10, 64)

}
